package tools.jackson.module.kotlin.kogeraIntegration.deser.valueClass.parameterSize.twoUnitPrimitive

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import tools.jackson.module.kotlin.assertReflectEquals
import tools.jackson.module.kotlin.callPrimaryConstructor
import tools.jackson.module.kotlin.defaultMapper
import tools.jackson.module.kotlin.kogeraIntegration.deser.valueClass.TwoUnitPrimitive
import tools.jackson.module.kotlin.readValue

/**
 * Up to argument size 32 there is one mask argument for the default argument,
 * 33 ~ 64 there are two, and 65 there are three, so each boundary value is tested.
 * Also, the maximum size of arguments that can be set by a constructor
 * that includes a value class as an argument is 126 (one less by DefaultConstructorMarker), so test that case as well.
 */
class DeserializeByConstructorWithoutDefaultArgumentsTest {
    data class Dst32(
        val p00: TwoUnitPrimitive,
        val p01: TwoUnitPrimitive,
        val p02: TwoUnitPrimitive,
        val p03: TwoUnitPrimitive,
        val p04: TwoUnitPrimitive,
        val p05: TwoUnitPrimitive,
        val p06: TwoUnitPrimitive,
        val p07: TwoUnitPrimitive,
        val p08: TwoUnitPrimitive,
        val p09: TwoUnitPrimitive,
        val p10: TwoUnitPrimitive,
        val p11: TwoUnitPrimitive,
        val p12: TwoUnitPrimitive,
        val p13: TwoUnitPrimitive,
        val p14: TwoUnitPrimitive,
        val p15: TwoUnitPrimitive,
        val p16: TwoUnitPrimitive,
        val p17: TwoUnitPrimitive,
        val p18: TwoUnitPrimitive,
        val p19: TwoUnitPrimitive,
        val p20: TwoUnitPrimitive,
        val p21: TwoUnitPrimitive,
        val p22: TwoUnitPrimitive,
        val p23: TwoUnitPrimitive,
        val p24: TwoUnitPrimitive,
        val p25: TwoUnitPrimitive,
        val p26: TwoUnitPrimitive,
        val p27: TwoUnitPrimitive,
        val p28: TwoUnitPrimitive,
        val p29: TwoUnitPrimitive,
        val p30: TwoUnitPrimitive,
        val p31: TwoUnitPrimitive
    )

    @Test
    fun test32() {
        val expected = callPrimaryConstructor<Dst32> { TwoUnitPrimitive(it.index.toLong()) }
        val src = defaultMapper.writeValueAsString(expected)
        Assertions.assertEquals(expected, defaultMapper.readValue<Dst32>(src))
    }

    data class Dst33(
        val p00: TwoUnitPrimitive,
        val p01: TwoUnitPrimitive,
        val p02: TwoUnitPrimitive,
        val p03: TwoUnitPrimitive,
        val p04: TwoUnitPrimitive,
        val p05: TwoUnitPrimitive,
        val p06: TwoUnitPrimitive,
        val p07: TwoUnitPrimitive,
        val p08: TwoUnitPrimitive,
        val p09: TwoUnitPrimitive,
        val p10: TwoUnitPrimitive,
        val p11: TwoUnitPrimitive,
        val p12: TwoUnitPrimitive,
        val p13: TwoUnitPrimitive,
        val p14: TwoUnitPrimitive,
        val p15: TwoUnitPrimitive,
        val p16: TwoUnitPrimitive,
        val p17: TwoUnitPrimitive,
        val p18: TwoUnitPrimitive,
        val p19: TwoUnitPrimitive,
        val p20: TwoUnitPrimitive,
        val p21: TwoUnitPrimitive,
        val p22: TwoUnitPrimitive,
        val p23: TwoUnitPrimitive,
        val p24: TwoUnitPrimitive,
        val p25: TwoUnitPrimitive,
        val p26: TwoUnitPrimitive,
        val p27: TwoUnitPrimitive,
        val p28: TwoUnitPrimitive,
        val p29: TwoUnitPrimitive,
        val p30: TwoUnitPrimitive,
        val p31: TwoUnitPrimitive,
        val p32: TwoUnitPrimitive
    )

    @Test
    fun test33() {
        val expected = callPrimaryConstructor<Dst33> { TwoUnitPrimitive(it.index.toLong()) }
        val src = defaultMapper.writeValueAsString(expected)
        Assertions.assertEquals(expected, defaultMapper.readValue<Dst33>(src))
    }

    data class Dst64(
        val p00: TwoUnitPrimitive,
        val p01: TwoUnitPrimitive,
        val p02: TwoUnitPrimitive,
        val p03: TwoUnitPrimitive,
        val p04: TwoUnitPrimitive,
        val p05: TwoUnitPrimitive,
        val p06: TwoUnitPrimitive,
        val p07: TwoUnitPrimitive,
        val p08: TwoUnitPrimitive,
        val p09: TwoUnitPrimitive,
        val p10: TwoUnitPrimitive,
        val p11: TwoUnitPrimitive,
        val p12: TwoUnitPrimitive,
        val p13: TwoUnitPrimitive,
        val p14: TwoUnitPrimitive,
        val p15: TwoUnitPrimitive,
        val p16: TwoUnitPrimitive,
        val p17: TwoUnitPrimitive,
        val p18: TwoUnitPrimitive,
        val p19: TwoUnitPrimitive,
        val p20: TwoUnitPrimitive,
        val p21: TwoUnitPrimitive,
        val p22: TwoUnitPrimitive,
        val p23: TwoUnitPrimitive,
        val p24: TwoUnitPrimitive,
        val p25: TwoUnitPrimitive,
        val p26: TwoUnitPrimitive,
        val p27: TwoUnitPrimitive,
        val p28: TwoUnitPrimitive,
        val p29: TwoUnitPrimitive,
        val p30: TwoUnitPrimitive,
        val p31: TwoUnitPrimitive,
        val p32: TwoUnitPrimitive,
        val p33: TwoUnitPrimitive,
        val p34: TwoUnitPrimitive,
        val p35: TwoUnitPrimitive,
        val p36: TwoUnitPrimitive,
        val p37: TwoUnitPrimitive,
        val p38: TwoUnitPrimitive,
        val p39: TwoUnitPrimitive,
        val p40: TwoUnitPrimitive,
        val p41: TwoUnitPrimitive,
        val p42: TwoUnitPrimitive,
        val p43: TwoUnitPrimitive,
        val p44: TwoUnitPrimitive,
        val p45: TwoUnitPrimitive,
        val p46: TwoUnitPrimitive,
        val p47: TwoUnitPrimitive,
        val p48: TwoUnitPrimitive,
        val p49: TwoUnitPrimitive,
        val p50: TwoUnitPrimitive,
        val p51: TwoUnitPrimitive,
        val p52: TwoUnitPrimitive,
        val p53: TwoUnitPrimitive,
        val p54: TwoUnitPrimitive,
        val p55: TwoUnitPrimitive,
        val p56: TwoUnitPrimitive,
        val p57: TwoUnitPrimitive,
        val p58: TwoUnitPrimitive,
        val p59: TwoUnitPrimitive,
        val p60: TwoUnitPrimitive,
        val p61: TwoUnitPrimitive,
        val p62: TwoUnitPrimitive,
        val p63: TwoUnitPrimitive
    )

    @Test
    fun test64() {
        val expected = callPrimaryConstructor<Dst64> { TwoUnitPrimitive(it.index.toLong()) }
        val src = defaultMapper.writeValueAsString(expected)
        Assertions.assertEquals(expected, defaultMapper.readValue<Dst64>(src))
    }

    data class Dst65(
        val p00: TwoUnitPrimitive,
        val p01: TwoUnitPrimitive,
        val p02: TwoUnitPrimitive,
        val p03: TwoUnitPrimitive,
        val p04: TwoUnitPrimitive,
        val p05: TwoUnitPrimitive,
        val p06: TwoUnitPrimitive,
        val p07: TwoUnitPrimitive,
        val p08: TwoUnitPrimitive,
        val p09: TwoUnitPrimitive,
        val p10: TwoUnitPrimitive,
        val p11: TwoUnitPrimitive,
        val p12: TwoUnitPrimitive,
        val p13: TwoUnitPrimitive,
        val p14: TwoUnitPrimitive,
        val p15: TwoUnitPrimitive,
        val p16: TwoUnitPrimitive,
        val p17: TwoUnitPrimitive,
        val p18: TwoUnitPrimitive,
        val p19: TwoUnitPrimitive,
        val p20: TwoUnitPrimitive,
        val p21: TwoUnitPrimitive,
        val p22: TwoUnitPrimitive,
        val p23: TwoUnitPrimitive,
        val p24: TwoUnitPrimitive,
        val p25: TwoUnitPrimitive,
        val p26: TwoUnitPrimitive,
        val p27: TwoUnitPrimitive,
        val p28: TwoUnitPrimitive,
        val p29: TwoUnitPrimitive,
        val p30: TwoUnitPrimitive,
        val p31: TwoUnitPrimitive,
        val p32: TwoUnitPrimitive,
        val p33: TwoUnitPrimitive,
        val p34: TwoUnitPrimitive,
        val p35: TwoUnitPrimitive,
        val p36: TwoUnitPrimitive,
        val p37: TwoUnitPrimitive,
        val p38: TwoUnitPrimitive,
        val p39: TwoUnitPrimitive,
        val p40: TwoUnitPrimitive,
        val p41: TwoUnitPrimitive,
        val p42: TwoUnitPrimitive,
        val p43: TwoUnitPrimitive,
        val p44: TwoUnitPrimitive,
        val p45: TwoUnitPrimitive,
        val p46: TwoUnitPrimitive,
        val p47: TwoUnitPrimitive,
        val p48: TwoUnitPrimitive,
        val p49: TwoUnitPrimitive,
        val p50: TwoUnitPrimitive,
        val p51: TwoUnitPrimitive,
        val p52: TwoUnitPrimitive,
        val p53: TwoUnitPrimitive,
        val p54: TwoUnitPrimitive,
        val p55: TwoUnitPrimitive,
        val p56: TwoUnitPrimitive,
        val p57: TwoUnitPrimitive,
        val p58: TwoUnitPrimitive,
        val p59: TwoUnitPrimitive,
        val p60: TwoUnitPrimitive,
        val p61: TwoUnitPrimitive,
        val p62: TwoUnitPrimitive,
        val p63: TwoUnitPrimitive,
        val p64: TwoUnitPrimitive
    )

    @Test
    fun test65() {
        val expected = callPrimaryConstructor<Dst65> { TwoUnitPrimitive(it.index.toLong()) }
        val src = defaultMapper.writeValueAsString(expected)
        Assertions.assertEquals(expected, defaultMapper.readValue<Dst65>(src))
    }

    // It cannot be a data class because the generated method would exceed the argument size limit.
    class DstMax(
        val p000: TwoUnitPrimitive,
        val p001: TwoUnitPrimitive,
        val p002: TwoUnitPrimitive,
        val p003: TwoUnitPrimitive,
        val p004: TwoUnitPrimitive,
        val p005: TwoUnitPrimitive,
        val p006: TwoUnitPrimitive,
        val p007: TwoUnitPrimitive,
        val p008: TwoUnitPrimitive,
        val p009: TwoUnitPrimitive,
        val p010: TwoUnitPrimitive,
        val p011: TwoUnitPrimitive,
        val p012: TwoUnitPrimitive,
        val p013: TwoUnitPrimitive,
        val p014: TwoUnitPrimitive,
        val p015: TwoUnitPrimitive,
        val p016: TwoUnitPrimitive,
        val p017: TwoUnitPrimitive,
        val p018: TwoUnitPrimitive,
        val p019: TwoUnitPrimitive,
        val p020: TwoUnitPrimitive,
        val p021: TwoUnitPrimitive,
        val p022: TwoUnitPrimitive,
        val p023: TwoUnitPrimitive,
        val p024: TwoUnitPrimitive,
        val p025: TwoUnitPrimitive,
        val p026: TwoUnitPrimitive,
        val p027: TwoUnitPrimitive,
        val p028: TwoUnitPrimitive,
        val p029: TwoUnitPrimitive,
        val p030: TwoUnitPrimitive,
        val p031: TwoUnitPrimitive,
        val p032: TwoUnitPrimitive,
        val p033: TwoUnitPrimitive,
        val p034: TwoUnitPrimitive,
        val p035: TwoUnitPrimitive,
        val p036: TwoUnitPrimitive,
        val p037: TwoUnitPrimitive,
        val p038: TwoUnitPrimitive,
        val p039: TwoUnitPrimitive,
        val p040: TwoUnitPrimitive,
        val p041: TwoUnitPrimitive,
        val p042: TwoUnitPrimitive,
        val p043: TwoUnitPrimitive,
        val p044: TwoUnitPrimitive,
        val p045: TwoUnitPrimitive,
        val p046: TwoUnitPrimitive,
        val p047: TwoUnitPrimitive,
        val p048: TwoUnitPrimitive,
        val p049: TwoUnitPrimitive,
        val p050: TwoUnitPrimitive,
        val p051: TwoUnitPrimitive,
        val p052: TwoUnitPrimitive,
        val p053: TwoUnitPrimitive,
        val p054: TwoUnitPrimitive,
        val p055: TwoUnitPrimitive,
        val p056: TwoUnitPrimitive,
        val p057: TwoUnitPrimitive,
        val p058: TwoUnitPrimitive,
        val p059: TwoUnitPrimitive,
        val p060: TwoUnitPrimitive,
        val p061: TwoUnitPrimitive,
        val p062: TwoUnitPrimitive,
        val p063: TwoUnitPrimitive,
        val p064: TwoUnitPrimitive,
        val p065: TwoUnitPrimitive,
        val p066: TwoUnitPrimitive,
        val p067: TwoUnitPrimitive,
        val p068: TwoUnitPrimitive,
        val p069: TwoUnitPrimitive,
        val p070: TwoUnitPrimitive,
        val p071: TwoUnitPrimitive,
        val p072: TwoUnitPrimitive,
        val p073: TwoUnitPrimitive,
        val p074: TwoUnitPrimitive,
        val p075: TwoUnitPrimitive,
        val p076: TwoUnitPrimitive,
        val p077: TwoUnitPrimitive,
        val p078: TwoUnitPrimitive,
        val p079: TwoUnitPrimitive,
        val p080: TwoUnitPrimitive,
        val p081: TwoUnitPrimitive,
        val p082: TwoUnitPrimitive,
        val p083: TwoUnitPrimitive,
        val p084: TwoUnitPrimitive,
        val p085: TwoUnitPrimitive,
        val p086: TwoUnitPrimitive,
        val p087: TwoUnitPrimitive,
        val p088: TwoUnitPrimitive,
        val p089: TwoUnitPrimitive,
        val p090: TwoUnitPrimitive,
        val p091: TwoUnitPrimitive,
        val p092: TwoUnitPrimitive,
        val p093: TwoUnitPrimitive,
        val p094: TwoUnitPrimitive,
        val p095: TwoUnitPrimitive,
        val p096: TwoUnitPrimitive,
        val p097: TwoUnitPrimitive,
        val p098: TwoUnitPrimitive,
        val p099: TwoUnitPrimitive,
        val p100: TwoUnitPrimitive,
        val p101: TwoUnitPrimitive,
        val p102: TwoUnitPrimitive,
        val p103: TwoUnitPrimitive,
        val p104: TwoUnitPrimitive,
        val p105: TwoUnitPrimitive,
        val p106: TwoUnitPrimitive,
        val p107: TwoUnitPrimitive,
        val p108: TwoUnitPrimitive,
        val p109: TwoUnitPrimitive,
        val p110: TwoUnitPrimitive,
        val p111: TwoUnitPrimitive,
        val p112: TwoUnitPrimitive,
        val p113: TwoUnitPrimitive,
        val p114: TwoUnitPrimitive,
        val p115: TwoUnitPrimitive,
        val p116: TwoUnitPrimitive,
        val p117: TwoUnitPrimitive,
        val p118: TwoUnitPrimitive,
        val p119: TwoUnitPrimitive,
        val p120: TwoUnitPrimitive,
        val p121: TwoUnitPrimitive,
        val p122: TwoUnitPrimitive,
        val p123: TwoUnitPrimitive,
        val p124: TwoUnitPrimitive,
        val p125: TwoUnitPrimitive
    )

    @Test
    fun testMax() {
        val expected = callPrimaryConstructor<DstMax> { TwoUnitPrimitive(it.index.toLong()) }
        val src = defaultMapper.writeValueAsString(expected)
        assertReflectEquals(expected, defaultMapper.readValue<DstMax>(src))
    }
}
